// ml278
// Copyright (C) 2008 Bjørn Øivind Bjørnsen, Aleksander Gjermundsen, Knut Andre Tidemann, Thomas Hansen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

#include "planetarylodjoint.h"
#include "planetaryscenemanager.h"
#include "planetaryoptions.h"
#include "planetaryheightmapdata.h"
#include "planetarypageheightmap.h"
#include "planetaryindexbuffermanager.h"
#include "planetarycommon.h"

#define DEBUG_IF_STATEMENT ((mRelation != NORTH && mRelation != SOUTH && mRelation != EAST && mRelation != WEST)&& mParentZone == ZONE_FRONT) || ((mRelation != NORTH && mRelation != SOUTH)&& mParentZone == ZONE_DOWN) || ((mRelation != NORTH && mRelation != SOUTH)&& mParentZone == ZONE_BACK) || ((mRelation != EAST && mRelation != WEST)&& mParentZone == ZONE_LEFT) || ((mRelation != EAST && mRelation != WEST)&& mParentZone == ZONE_RIGHT)

namespace Ogre
{	
	String PlanetaryLODJoint::mType = "PlanetaryLODJoint";

	PlanetaryLODJoint::PlanetaryLODJoint(PlanetarySceneManager *mgr) : Renderable(), MovableObject()
	{
		mSceneMgr = mgr;
		mOptions = mgr->getOptions();
		mPlanet = 0;
		mIsLoaded = false;
		mIsInit = false;
		mScale = mOptions->mPlanetRadius;
	}

	void PlanetaryLODJoint::init(unsigned int parentZone, unsigned int neighbourZone,NEIGHBOUR relation,SceneNode *pNode)
	{
		assert(!mIsInit);

		mRelation = relation;
		mParentZone = parentZone;
		mNeighbourZone = neighbourZone;
		mSceneNode = pNode;

		mCastShadows = false;
		
		mName = "PlanetaryLODJoint::" + StringConverter::toString(parentZone) + "::" + StringConverter::toString(neighbourZone);

		if(DEBUG_IF_STATEMENT)
			return;

		const unsigned int rowlength = mOptions->mZoneSizeLOD1;
		const unsigned int rowlength2 = (mOptions->mPageSizeLOD1 - 1) * mOptions->ZoneSize + 1;

		String matname = mOptions->mPlanetMaterial + "/Zone_" + StringConverter::toString(parentZone+1,2,'0');
		//mMaterial = MaterialManager::getSingleton().getByName(matname);
		mMaterial = MaterialManager::getSingleton().getByName(mOptions->mPlanetMaterial + "_groundFromSpace");
		//mMaterial = MaterialManager::getSingleton().getByName("DontCullMePlx");

		// Default query flags to top bit so users can exclude it if they wish
		MovableObject::mQueryFlags = SceneManager::WORLD_GEOMETRY_TYPE_MASK;
		MovableObject::setRenderQueueGroup(mSceneMgr->getWorldGeometryRenderQueue());

		mVertexes = new VertexData();
		mVertexes->vertexStart = 0;
		mVertexes->vertexCount = rowlength + rowlength2;

		VertexDeclaration *decl = mVertexes->vertexDeclaration;

		size_t offset = 0;
		decl->addElement(0,0,VET_FLOAT3,VES_POSITION);
		offset += VertexElement::getTypeSize(VET_FLOAT3);
		decl->addElement(0,offset,VET_FLOAT3, VES_NORMAL);
		offset += VertexElement::getTypeSize(VET_FLOAT3);
		decl->addElement(0,offset,VET_FLOAT2, VES_TEXTURE_COORDINATES);
		offset += VertexElement::getTypeSize(VET_FLOAT2);

		mIndexes = new IndexData();
		mIndexes->indexStart = 0;
		mIndexes->indexCount = mSceneMgr->getIndexBufferManager()->getIndexBufferSize(INDEX_BUFFER_ZONE_TO_PAGE_JOINT);//3 * (rowlength2 - 1) + 3 * (rowlength - 1);

		mIsInit = true;
	}

	void PlanetaryLODJoint::load()
	{
		if(DEBUG_IF_STATEMENT)
			return;

		mBounds.setNull();

		VertexDeclaration *decl = mVertexes->vertexDeclaration;
		VertexBufferBinding *bind = mVertexes->vertexBufferBinding;

		// Setup vertices
		HardwareVertexBufferSharedPtr vbuf = 
			HardwareBufferManager::getSingleton().createVertexBuffer(
				decl->getVertexSize(0),
				mVertexes->vertexCount,
				HardwareBuffer::HBU_STATIC_WRITE_ONLY);

		bind->setBinding(0,vbuf);

		const VertexElement* poselem = decl->findElementBySemantic(VES_POSITION);

		unsigned int vertexSize = vbuf->getVertexSize();

		uchar *pBuffer = (uchar*)vbuf->lock(HardwareBuffer::HBL_DISCARD);

		/// Insert vertices
		switch(mParentZone)
		{
			case ZONE_UP:
				loadUp(poselem,pBuffer,vertexSize);
				break;

			case ZONE_DOWN:
				loadDown(poselem,pBuffer,vertexSize);
				break;
			
			case ZONE_FRONT:
				loadFront(poselem,pBuffer,vertexSize);
				break;
			
			case ZONE_BACK:
				loadBack(poselem,pBuffer,vertexSize);
				break;
		
			case ZONE_LEFT:
				loadLeft(poselem,pBuffer,vertexSize);
				break;
			
			case ZONE_RIGHT:
				loadRight(poselem,pBuffer,vertexSize);
				break;
		}

		vbuf->unlock();

		// Setup indices
		mIndexes->indexBuffer = mSceneMgr->getIndexBufferManager()->getIndexBuffer(INDEX_BUFFER_ZONE_TO_PAGE_JOINT);

		float x = (mBounds.getMaximum().x - mBounds.getMinimum().x);
		float y = (mBounds.getMaximum().y - mBounds.getMinimum().y);
		float z = (mBounds.getMaximum().y - mBounds.getMinimum().y);

		mCenter = Vector3(mBounds.getMinimum().x + (x/2.0f),mBounds.getMinimum().y + (y/2.0f),mBounds.getMinimum().z + (z/2.0f));

		mBoundingRadius = Math::Sqrt(Math::Sqr(x) + Math::Sqr(y) + Math::Sqr(z)) / 2.0f;

		mIsLoaded = true;
	}

	void PlanetaryLODJoint::unload()
	{
		assert(mIsLoaded);

		mVertexes->vertexBufferBinding->unsetAllBindings();
		mIndexes->indexBuffer.setNull();

		mIsLoaded = false;
	}

	void PlanetaryLODJoint::uninit()
	{
		assert(mIsInit);

		mVertexes->vertexDeclaration->removeAllElements();
		delete mVertexes;
		mVertexes = NULL;

		delete mIndexes;
		mIndexes = NULL;

		mParentZone = 0;
		mNeighbourZone = 0;

		mIsInit = false;
	}

	void PlanetaryLODJoint::_notifyCurrentCamera(Camera* cam)
	{
		if(!mIsLoaded || !mIsInit)
		{
			mVisible = false;
			return;
		}

		mVisible = true;
	}

	void PlanetaryLODJoint::_updateRenderQueue(RenderQueue* queue)
	{
		queue->addRenderable(this);
	}

	void PlanetaryLODJoint::_notifyAttached(Node* parent, bool isTagPoint)
	{
		MovableObject::_notifyAttached(parent, isTagPoint);
	}

	void PlanetaryLODJoint::getRenderOperation(RenderOperation& op)
	{
		op.useIndexes = true;
		op.operationType = RenderOperation::OT_TRIANGLE_LIST;
		op.vertexData = mVertexes;
		op.indexData = mIndexes;
	}

	void PlanetaryLODJoint::getWorldTransforms(Matrix4 *xform) const
	{
		*xform = mParentNode->_getFullTransform();
	}

	const Quaternion &PlanetaryLODJoint::getWorldOrientation() const
	{
		return mParentNode->_getDerivedOrientation();
	}

	const Vector3 &PlanetaryLODJoint::getWorldPosition() const
	{
		return mCenter;
	}
	
	Real PlanetaryLODJoint::getSquaredViewDepth(const Camera *cam) const
	{
		return (PlanetaryLODJoint::getWorldPosition() - cam->getDerivedPosition()).squaredLength();
	}

	const LightList &PlanetaryLODJoint::getLights() const
	{
		if (mLightListDirty)
		{
			getParentSceneNode()->getCreator()->_populateLightList(
					mCenter, 
					this->getBoundingRadius(), 
					mLightList);
					mLightListDirty = false;
		}
		return mLightList;
	}

	void PlanetaryLODJoint::show(bool show)
	{	
		if(DEBUG_IF_STATEMENT)
			return;

		if(show)
		{
			LogManager::getSingletonPtr()->logMessage("Showing " + zoneToStr(mParentZone) + "::" + relationToStr(mRelation) + " joint");
			mVisible = true;
			mSceneNode->attachObject(this);
		}
		else
		{
			LogManager::getSingletonPtr()->logMessage("Hiding " + zoneToStr(mParentZone) + "::" + relationToStr(mRelation) + " joint");
			mVisible = false;
			mSceneNode->detachObject(this);
		}
	}
	
	void PlanetaryLODJoint::loadUp(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize)
	{
		const PlanetaryHeightmapData *hdata = mSceneMgr->getHeightmapData();
		const PlanetaryZoneHeightmap *heightmap = hdata->getZoneHeightmap(mPlanet,mParentZone);
		const float *fh;
		float *pPos;
		
		// Insert parent vertices first			
		for(unsigned int i = 0; i < mOptions->mZoneSizeLOD1; i++)
		{
			float x,y,z;
			float hscale;
				
			switch(mRelation)
			{
				case NORTH:
					x = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					z = -1.0f;
					fh = heightmap->getRow(0);
					hscale = 1.0f + (((fh[(mOptions->mZoneSizeLOD1 - 1) - i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
				
				case SOUTH:
					x = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					z = 1.0f;
					fh = heightmap->getRow(mOptions->mZoneSizeLOD1 - 1);
					hscale = 1.0f + (((fh[i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case EAST:
					x = 1.0f;
					z = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					fh = heightmap->getRow((mOptions->mZoneSizeLOD1 - 1) - i);
					hscale = 1.0f + (((fh[mOptions->mZoneSizeLOD1 - 1] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case WEST:
					x = -1.0f;
					z = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					fh = heightmap->getRow(i);
					hscale = 1.0f + (((fh[0] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
			}

			y = 1.0f;

			//if(mRelation == EAST)
			//	LogManager::getSingletonPtr()->logMessage("Parent: (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");

			Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;

			poselem->baseVertexPointerToElement(pBuffer, &pPos);

			mBounds.merge(pos);

			// Vertex coords
			*pPos++ = pos.x; // X
			*pPos++ = pos.y; // Y
			*pPos++ = pos.z; // Z

			// Normals
			Vector3 norm = pos.normalisedCopy();
			*pPos++ = norm.x; // X
			*pPos++ = norm.y; // Y
			*pPos++ = norm.z; // Z

			// Texture Coords
			//Vector2 tex(((x + 1.0f) / 2), ((z + 1.0f) / 2));
			Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
			*pPos++ = tex.x;
			*pPos++ = tex.y;

			pBuffer += vertexSize;
		}
			
		// Insert child vertices
		for(unsigned int i = 0; i < mOptions->ZoneSize; i++)
		{
			const PlanetaryPageHeightmap *heightmap;
			switch(mRelation)
			{
				case NORTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,(mOptions->ZoneSize - 1) - i,mOptions->ZoneSize - 1,1);
					break;
				case SOUTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
				case EAST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
				case WEST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
			}

			for(unsigned int j = 0; j < mOptions->mPageSizeLOD1; j++)
			{
				if(i != 0 && j == 0)
					continue;
					
				float zoneSize = static_cast<float>(mOptions->ZoneSize * (mOptions->mPageSizeLOD1 - 1));
					
				float x,y,z;
				
				const float *fh;
				float hscale;
					
				switch(mRelation)
				{
					case NORTH:
						x = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) + 1.0f;
						z = -1.0f;
						
						fh = heightmap->getRow(mOptions->mPageSizeLOD1 - 1,1);
						hscale = 1.0f + (((fh[(mOptions->mPageSizeLOD1 - 1) - j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case SOUTH:
						x = (2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) - 1.0f;
						z = 1.0f;

						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case EAST:
						x = 1.0f;
						z = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) / 
							zoneSize)) + 1.0f;
						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case WEST:
						x = -1.0f;
						z = ( 2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) - 1.0f;
						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
				}

				y = 1.0f;
				
				//if(mRelation == EAST)
				//	LogManager::getSingletonPtr()->logMessage("Child:   (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");
			
				Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;
			
				poselem->baseVertexPointerToElement(pBuffer, &pPos);
			
				mBounds.merge(pos);
			
							// Vertex coords
				*pPos++ = pos.x; // X
				*pPos++ = pos.y; // Y
				*pPos++ = pos.z; // Z
			
							// Normals
				Vector3 norm = pos.normalisedCopy();
				*pPos++ = norm.x; // X
				*pPos++ = norm.y; // Y
				*pPos++ = norm.z; // Z
			
					// Texture Coords
				Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
				*pPos++ = tex.x;
				*pPos++ = tex.y;
			
				pBuffer += vertexSize ;
			}
		}
	}
	
	void PlanetaryLODJoint::loadDown(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize)
	{
		const PlanetaryHeightmapData *hdata = mSceneMgr->getHeightmapData();
		const PlanetaryZoneHeightmap *heightmap = hdata->getZoneHeightmap(mPlanet,mParentZone);
		const float *fh;
		float *pPos;
		
		// Insert parent vertices first			
		for(unsigned int i = 0; i < mOptions->mZoneSizeLOD1; i++)
		{
			float x,y,z;
			float hscale;
				
			switch(mRelation)
			{
				case NORTH:
					x = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					z = 1.0f;
					fh = heightmap->getRow(0);
					hscale = 1.0f + (((fh[(mOptions->mZoneSizeLOD1 - 1) - i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
				
				case SOUTH:
					x = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					z = -1.0f;
					fh = heightmap->getRow(mOptions->mZoneSizeLOD1 - 1);
					hscale = 1.0f + (((fh[i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case EAST:
					x = 1.0f;
					z = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					fh = heightmap->getRow((mOptions->mZoneSizeLOD1 - 1) - i);
					hscale = 1.0f + (((fh[mOptions->mZoneSizeLOD1 - 1] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case WEST:
					x = -1.0f;
					z = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					fh = heightmap->getRow(i);
					hscale = 1.0f + (((fh[0] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
			}

			y = -1.0f;

			//if(mRelation == EAST)
			//	LogManager::getSingletonPtr()->logMessage("Parent: (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");

			Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;

			poselem->baseVertexPointerToElement(pBuffer, &pPos);

			mBounds.merge(pos);

			// Vertex coords
			*pPos++ = pos.x; // X
			*pPos++ = pos.y; // Y
			*pPos++ = pos.z; // Z

			// Normals
			Vector3 norm = pos.normalisedCopy();
			*pPos++ = norm.x; // X
			*pPos++ = norm.y; // Y
			*pPos++ = norm.z; // Z

			// Texture Coords
			//Vector2 tex(((x + 1.0f) / 2), ((z + 1.0f) / 2));
			Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
			*pPos++ = tex.x;
			*pPos++ = tex.y;

			pBuffer += vertexSize;
		}
			
		// Insert child vertices
		for(unsigned int i = 0; i < mOptions->ZoneSize; i++)
		{
			const PlanetaryPageHeightmap *heightmap;
			switch(mRelation)
			{
				case NORTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,(mOptions->ZoneSize - 1) - i,mOptions->ZoneSize - 1,1);
					break;
				case SOUTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
				case EAST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
				case WEST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
			}

			for(unsigned int j = 0; j < mOptions->mPageSizeLOD1; j++)
			{
				if(i != 0 && j == 0)
					continue;
					
				float zoneSize = static_cast<float>(mOptions->ZoneSize * (mOptions->mPageSizeLOD1 - 1));
					
				float x,y,z;
				
				const float *fh;
				float hscale;
					
				switch(mRelation)
				{
					case NORTH:
						x = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) + 1.0f;
						z = 1.0f;
						
						fh = heightmap->getRow(mOptions->mPageSizeLOD1 - 1,1);
						hscale = 1.0f + (((fh[(mOptions->mPageSizeLOD1 - 1) - j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case SOUTH:
						x = (2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) - 1.0f;
						z = -1.0f;

						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case EAST:
						x = 1.0f;
						z = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) / 
							zoneSize)) + 1.0f;
						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case WEST:
						x = -1.0f;
						z = ( 2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) - 1.0f;
						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
				}

				y = -1.0f;
				
				//if(mRelation == EAST)
				//	LogManager::getSingletonPtr()->logMessage("Child:   (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");
			
				Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;
			
				poselem->baseVertexPointerToElement(pBuffer, &pPos);
			
				mBounds.merge(pos);
			
							// Vertex coords
				*pPos++ = pos.x; // X
				*pPos++ = pos.y; // Y
				*pPos++ = pos.z; // Z
			
							// Normals
				Vector3 norm = pos.normalisedCopy();
				*pPos++ = norm.x; // X
				*pPos++ = norm.y; // Y
				*pPos++ = norm.z; // Z
			
					// Texture Coords
				Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
				*pPos++ = tex.x;
				*pPos++ = tex.y;
			
				pBuffer += vertexSize ;
			}
		}
	}
	
	void PlanetaryLODJoint::loadFront(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize)
	{
		const PlanetaryHeightmapData *hdata = mSceneMgr->getHeightmapData();
		const PlanetaryZoneHeightmap *heightmap = hdata->getZoneHeightmap(mPlanet,mParentZone);
		const float *fh;
		float *pPos;
		
		// Insert parent vertices first			
		for(unsigned int i = 0; i < mOptions->mZoneSizeLOD1; i++)
		{
			float x,y,z;
			float hscale;
				
			switch(mRelation)
			{
				case NORTH:
					x = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					y = 1.0f;
					fh = heightmap->getRow(0);
					hscale = 1.0f + (((fh[(mOptions->mZoneSizeLOD1 - 1) - i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
				
				case SOUTH:
					x = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					y = -1.0f;
					fh = heightmap->getRow(mOptions->mZoneSizeLOD1 - 1);
					hscale = 1.0f + (((fh[i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case EAST:
					x = 1.0f;
					y = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					fh = heightmap->getRow((mOptions->mZoneSizeLOD1 - 1) - i);
					hscale = 1.0f + (((fh[mOptions->mZoneSizeLOD1 - 1] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case WEST:
					x = -1.0f;
					y = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					fh = heightmap->getRow(i);
					hscale = 1.0f + (((fh[0] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
			}

			z = 1.0f;

			//if(mRelation == EAST)
			//	LogManager::getSingletonPtr()->logMessage("Parent: (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");

			Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;

			poselem->baseVertexPointerToElement(pBuffer, &pPos);

			mBounds.merge(pos);

			// Vertex coords
			*pPos++ = pos.x; // X
			*pPos++ = pos.y; // Y
			*pPos++ = pos.z; // Z

			// Normals
			Vector3 norm = pos.normalisedCopy();
			*pPos++ = norm.x; // X
			*pPos++ = norm.y; // Y
			*pPos++ = norm.z; // Z

			// Texture Coords
			//Vector2 tex(((x + 1.0f) / 2), ((z + 1.0f) / 2));
			Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
			*pPos++ = tex.x;
			*pPos++ = tex.y;

			pBuffer += vertexSize;
		}
			
		// Insert child vertices
		for(unsigned int i = 0; i < mOptions->ZoneSize; i++)
		{
			const PlanetaryPageHeightmap *heightmap;
			switch(mRelation)
			{
				case NORTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,(mOptions->ZoneSize - 1) - i,mOptions->ZoneSize - 1,1);
					break;
				case SOUTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
				case EAST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,0,(mOptions->ZoneSize - 1) - i,1);
					break;
				case WEST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,(mOptions->ZoneSize - 1),i,1);
					break;
			}

			for(unsigned int j = 0; j < mOptions->mPageSizeLOD1; j++)
			{
				if(i != 0 && j == 0)
					continue;
					
				float zoneSize = static_cast<float>(mOptions->ZoneSize * (mOptions->mPageSizeLOD1 - 1));
					
				float x,y,z;
				
				const float *fh;
				float hscale;
					
				switch(mRelation)
				{
					case NORTH:
						x = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) + 1.0f;
						y = 1.0f;
						
						fh = heightmap->getRow(mOptions->mPageSizeLOD1 - 1,1);
						hscale = 1.0f + (((fh[(mOptions->mPageSizeLOD1 - 1) - j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case SOUTH:
						x = (2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) - 1.0f;
						y = -1.0f;

						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case EAST:
						x = 1.0f;
						y = (2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) / 
							zoneSize)) - 1.0f;
						fh = heightmap->getRow((mOptions->mPageSizeLOD1 - 1) - j,1);
						hscale = 1.0f + (((fh[0] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case WEST:
						x = -1.0f;
						y = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) + 1.0f;
						fh = heightmap->getRow(j,1);
						hscale = 1.0f + (((fh[(mOptions->mPageSizeLOD1 - 1)] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
				}

				z = 1.0f;
				
				//if(mRelation == EAST)
				//	LogManager::getSingletonPtr()->logMessage("Child:   (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");
			
				Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;
			
				poselem->baseVertexPointerToElement(pBuffer, &pPos);
			
				mBounds.merge(pos);
			
							// Vertex coords
				*pPos++ = pos.x; // X
				*pPos++ = pos.y; // Y
				*pPos++ = pos.z; // Z
			
							// Normals
				Vector3 norm = pos.normalisedCopy();
				*pPos++ = norm.x; // X
				*pPos++ = norm.y; // Y
				*pPos++ = norm.z; // Z
			
					// Texture Coords
				Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
				*pPos++ = tex.x;
				*pPos++ = tex.y;
			
				pBuffer += vertexSize ;
			}
		}
	}
		
	void PlanetaryLODJoint::loadBack(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize)
	{
		const PlanetaryHeightmapData *hdata = mSceneMgr->getHeightmapData();
		const PlanetaryZoneHeightmap *heightmap = hdata->getZoneHeightmap(mPlanet,mParentZone);
		const float *fh;
		float *pPos;
		
		// Insert parent vertices first			
		for(unsigned int i = 0; i < mOptions->mZoneSizeLOD1; i++)
		{
			float x,y,z;
			float hscale;
				
			switch(mRelation)
			{
				case NORTH:
					x = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					y = -1.0f;
					fh = heightmap->getRow(0);
					hscale = 1.0f + (((fh[(mOptions->mZoneSizeLOD1 - 1) - i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
				
				case SOUTH:
					x = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					y = 1.0f;
					fh = heightmap->getRow(mOptions->mZoneSizeLOD1 - 1);
					hscale = 1.0f + (((fh[i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case EAST:
					x = 1.0f;
					y = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					fh = heightmap->getRow((mOptions->mZoneSizeLOD1 - 1) - i);
					hscale = 1.0f + (((fh[mOptions->mZoneSizeLOD1 - 1] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case WEST:
					x = -1.0f;
					y = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					fh = heightmap->getRow(i);
					hscale = 1.0f + (((fh[0] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
			}

			z = -1.0f;

			//if(mRelation == EAST)
			//	LogManager::getSingletonPtr()->logMessage("Parent: (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");

			Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;

			poselem->baseVertexPointerToElement(pBuffer, &pPos);

			mBounds.merge(pos);

			// Vertex coords
			*pPos++ = pos.x; // X
			*pPos++ = pos.y; // Y
			*pPos++ = pos.z; // Z

			// Normals
			Vector3 norm = pos.normalisedCopy();
			*pPos++ = norm.x; // X
			*pPos++ = norm.y; // Y
			*pPos++ = norm.z; // Z

			// Texture Coords
			//Vector2 tex(((x + 1.0f) / 2), ((z + 1.0f) / 2));
			Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
			*pPos++ = tex.x;
			*pPos++ = tex.y;

			pBuffer += vertexSize;
		}
			
		// Insert child vertices
		for(unsigned int i = 0; i < mOptions->ZoneSize; i++)
		{
			const PlanetaryPageHeightmap *heightmap;
			switch(mRelation)
			{
				case NORTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,(mOptions->ZoneSize - 1) - i,mOptions->ZoneSize - 1,1);
					break;
				case SOUTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
				case EAST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
				case WEST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
			}

			for(unsigned int j = 0; j < mOptions->mPageSizeLOD1; j++)
			{
				if(i != 0 && j == 0)
					continue;
					
				float zoneSize = static_cast<float>(mOptions->ZoneSize * (mOptions->mPageSizeLOD1 - 1));
					
				float x,y,z;
				
				const float *fh;
				float hscale;
					
				switch(mRelation)
				{
					case NORTH:
						x = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) + 1.0f;
						y = -1.0f;
						
						fh = heightmap->getRow(mOptions->mPageSizeLOD1 - 1,1);
						hscale = 1.0f + (((fh[(mOptions->mPageSizeLOD1 - 1) - j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case SOUTH:
						x = (2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) - 1.0f;
						y = 1.0f;

						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case EAST:
						x = 1.0f;
						y = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) / 
							zoneSize)) + 1.0f;
						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case WEST:
						x = -1.0f;
						y = ( 2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) - 1.0f;
						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
				}

				z = -1.0f;
				
				//if(mRelation == EAST)
				//	LogManager::getSingletonPtr()->logMessage("Child:   (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");
			
				Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;
			
				poselem->baseVertexPointerToElement(pBuffer, &pPos);
			
				mBounds.merge(pos);
			
							// Vertex coords
				*pPos++ = pos.x; // X
				*pPos++ = pos.y; // Y
				*pPos++ = pos.z; // Z
			
							// Normals
				Vector3 norm = pos.normalisedCopy();
				*pPos++ = norm.x; // X
				*pPos++ = norm.y; // Y
				*pPos++ = norm.z; // Z
			
					// Texture Coords
				Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
				*pPos++ = tex.x;
				*pPos++ = tex.y;
			
				pBuffer += vertexSize ;
			}
		}
	}
	
	void PlanetaryLODJoint::loadLeft(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize)
	{
		const PlanetaryHeightmapData *hdata = mSceneMgr->getHeightmapData();
		const PlanetaryZoneHeightmap *heightmap = hdata->getZoneHeightmap(mPlanet,mParentZone);
		const float *fh;
		float *pPos;
		
		// Insert parent vertices first			
		for(unsigned int i = 0; i < mOptions->mZoneSizeLOD1; i++)
		{
			float x,y,z;
			float hscale;
				
			switch(mRelation)
			{
				case NORTH:
					z = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					y = 1.0f;
					fh = heightmap->getRow(0);
					hscale = 1.0f + (((fh[(mOptions->mZoneSizeLOD1 - 1) - i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
				
				case SOUTH:
					z = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					y = -1.0f;
					fh = heightmap->getRow(mOptions->mZoneSizeLOD1 - 1);
					hscale = 1.0f + (((fh[i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case EAST:
					z = 1.0f;
					y = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					fh = heightmap->getRow((mOptions->mZoneSizeLOD1 - 1) - i);
					hscale = 1.0f + (((fh[mOptions->mZoneSizeLOD1 - 1] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case WEST:
					z = -1.0f;
					y = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					fh = heightmap->getRow(i);
					hscale = 1.0f + (((fh[0] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
			}

			x = -1.0f;

			//if(mRelation == EAST)
			//	LogManager::getSingletonPtr()->logMessage("Parent: (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");

			Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;

			poselem->baseVertexPointerToElement(pBuffer, &pPos);

			mBounds.merge(pos);

			// Vertex coords
			*pPos++ = pos.x; // X
			*pPos++ = pos.y; // Y
			*pPos++ = pos.z; // Z

			// Normals
			Vector3 norm = pos.normalisedCopy();
			*pPos++ = norm.x; // X
			*pPos++ = norm.y; // Y
			*pPos++ = norm.z; // Z

			// Texture Coords
			//Vector2 tex(((x + 1.0f) / 2), ((z + 1.0f) / 2));
			Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
			*pPos++ = tex.x;
			*pPos++ = tex.y;

			pBuffer += vertexSize;
		}
			
		// Insert child vertices
		for(unsigned int i = 0; i < mOptions->ZoneSize; i++)
		{
			const PlanetaryPageHeightmap *heightmap;
			switch(mRelation)
			{
				case NORTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,(mOptions->ZoneSize - 1) - i,mOptions->ZoneSize - 1,1);
					break;
				case SOUTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
				case EAST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,0,(mOptions->ZoneSize - 1) - i,1);
					break;
				case WEST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,0,(mOptions->ZoneSize - 1) - i,1);
					break;
			}

			for(unsigned int j = 0; j < mOptions->mPageSizeLOD1; j++)
			{
				if(i != 0 && j == 0)
					continue;
					
				float zoneSize = static_cast<float>(mOptions->ZoneSize * (mOptions->mPageSizeLOD1 - 1));
					
				float x,y,z;
				
				const float *fh;
				float hscale;
					
				switch(mRelation)
				{
					case NORTH:
						z = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) + 1.0f;
						y = 1.0f;
						
						fh = heightmap->getRow(mOptions->mPageSizeLOD1 - 1,1);
						hscale = 1.0f + (((fh[(mOptions->mPageSizeLOD1 - 1) - j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case SOUTH:
						z = (2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) - 1.0f;
						y = -1.0f;

						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case EAST:
						z = 1.0f;
						y = (2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) / 
							zoneSize)) - 1.0f;
						fh = heightmap->getRow((mOptions->mPageSizeLOD1 - 1) - j,1);
						hscale = 1.0f + (((fh[0] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case WEST:
						z = -1.0f;
						y = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) + 1.0f;
						fh = heightmap->getRow((mOptions->mPageSizeLOD1 - 1) - j,1);
						hscale = 1.0f + (((fh[0] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
				}

				x = -1.0f;
				
				//if(mRelation == EAST)
				//	LogManager::getSingletonPtr()->logMessage("Child:   (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");
			
				Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;
			
				poselem->baseVertexPointerToElement(pBuffer, &pPos);
			
				mBounds.merge(pos);
			
							// Vertex coords
				*pPos++ = pos.x; // X
				*pPos++ = pos.y; // Y
				*pPos++ = pos.z; // Z
			
							// Normals
				Vector3 norm = pos.normalisedCopy();
				*pPos++ = norm.x; // X
				*pPos++ = norm.y; // Y
				*pPos++ = norm.z; // Z
			
					// Texture Coords
				Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
				*pPos++ = tex.x;
				*pPos++ = tex.y;
			
				pBuffer += vertexSize ;
			}
		}
	}
	
	void PlanetaryLODJoint::loadRight(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize)
	{
		const PlanetaryHeightmapData *hdata = mSceneMgr->getHeightmapData();
		const PlanetaryZoneHeightmap *heightmap = hdata->getZoneHeightmap(mPlanet,mParentZone);
		const float *fh;
		float *pPos;
		
		// Insert parent vertices first			
		for(unsigned int i = 0; i < mOptions->mZoneSizeLOD1; i++)
		{
			float x,y,z;
			float hscale;
				
			switch(mRelation)
			{
				case NORTH:
					z = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					y = 1.0f;
					fh = heightmap->getRow(0);
					hscale = 1.0f + (((fh[(mOptions->mZoneSizeLOD1 - 1) - i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
				
				case SOUTH:
					z = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					y = -1.0f;
					fh = heightmap->getRow(mOptions->mZoneSizeLOD1 - 1);
					hscale = 1.0f + (((fh[i] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case EAST:
					z = -1.0f;
					y = (2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) - 1.0f;
					fh = heightmap->getRow((mOptions->mZoneSizeLOD1 - 1) - i);
					hscale = 1.0f + (((fh[mOptions->mZoneSizeLOD1 - 1] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
					
				case WEST:
					z = 1.0f;
					y = (-2.0f * static_cast<float>(i)/static_cast<float>(mOptions->mZoneSizeLOD1 - 1)) + 1.0f;
					fh = heightmap->getRow(i);
					hscale = 1.0f + (((fh[0] - 32768) / 65536) * mOptions->mTerrainScale);
					break;
			}

			x = 1.0f;

			//if(mRelation == EAST)
			//	LogManager::getSingletonPtr()->logMessage("Parent: (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");

			Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;

			poselem->baseVertexPointerToElement(pBuffer, &pPos);

			mBounds.merge(pos);

			// Vertex coords
			*pPos++ = pos.x; // X
			*pPos++ = pos.y; // Y
			*pPos++ = pos.z; // Z

			// Normals
			Vector3 norm = pos.normalisedCopy();
			*pPos++ = norm.x; // X
			*pPos++ = norm.y; // Y
			*pPos++ = norm.z; // Z

			// Texture Coords
			//Vector2 tex(((x + 1.0f) / 2), ((z + 1.0f) / 2));
			Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
			*pPos++ = tex.x;
			*pPos++ = tex.y;

			pBuffer += vertexSize;
		}
			
		// Insert child vertices
		for(unsigned int i = 0; i < mOptions->ZoneSize; i++)
		{
			const PlanetaryPageHeightmap *heightmap;
			switch(mRelation)
			{
				case NORTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,(mOptions->ZoneSize - 1) - i,mOptions->ZoneSize - 1,1);
					break;
				case SOUTH:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,i,0,1);
					break;
				case EAST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,(mOptions->ZoneSize -1),i,1);
					break;
				case WEST:
					heightmap = hdata->getHeightmap(mPlanet,mNeighbourZone,(mOptions->ZoneSize - 1),i,1);
					break;
			}

			for(unsigned int j = 0; j < mOptions->mPageSizeLOD1; j++)
			{
				if(i != 0 && j == 0)
					continue;
					
				float zoneSize = static_cast<float>(mOptions->ZoneSize * (mOptions->mPageSizeLOD1 - 1));
					
				float x,y,z;
				
				const float *fh;
				float hscale;
					
				switch(mRelation)
				{
					case NORTH:
						z = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) + 1.0f;
						y = 1.0f;
						
						fh = heightmap->getRow(mOptions->mPageSizeLOD1 - 1,1);
						hscale = 1.0f + (((fh[(mOptions->mPageSizeLOD1 - 1) - j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case SOUTH:
						z = (2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) - 1.0f;
						y = -1.0f;

						fh = heightmap->getRow(0,1);
						hscale = 1.0f + (((fh[j] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case EAST:
						z = -1.0f;
						y = (2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) / 
							zoneSize)) - 1.0f;
						fh = heightmap->getRow(j,1);
						hscale = 1.0f + (((fh[(mOptions->mPageSizeLOD1 - 1)] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
					case WEST:
						z = 1.0f;
						y = (-2.0f * (static_cast<float>((i * (mOptions->mPageSizeLOD1 - 1)) + j) /
								zoneSize)) + 1.0f;
						fh = heightmap->getRow(j,1);
						hscale = 1.0f + (((fh[(mOptions->mPageSizeLOD1 - 1)] - 32768) / 65536) * mOptions->mTerrainScale);
						break;
				}

				x = 1.0f;
				
				//if(mRelation == EAST)
				//	LogManager::getSingletonPtr()->logMessage("Child:   (" + StringConverter::toString(x) + "," + StringConverter::toString(y) + "," + StringConverter::toString(z) + ")");
			
				Vector3 pos = cubeToSphereCoords(x,y,z) * mScale * hscale;
			
				poselem->baseVertexPointerToElement(pBuffer, &pPos);
			
				mBounds.merge(pos);
			
							// Vertex coords
				*pPos++ = pos.x; // X
				*pPos++ = pos.y; // Y
				*pPos++ = pos.z; // Z
			
							// Normals
				Vector3 norm = pos.normalisedCopy();
				*pPos++ = norm.x; // X
				*pPos++ = norm.y; // Y
				*pPos++ = norm.z; // Z
			
					// Texture Coords
				Vector2 tex(static_cast<float>(i) / static_cast<float>(mOptions->mZoneSizeLOD1), 1.0f);
				*pPos++ = tex.x;
				*pPos++ = tex.y;
			
				pBuffer += vertexSize ;
			}
		}
	}
}
